process.env.NODE_ENV = "development";

import electron from "electron";
import { spawn } from "child_process";
import { createRequire } from "module";
import { createServer, build as viteBuild } from "vite";
import chalk from "chalk";
import { platform } from "os";
import { existsSync, cpSync } from "fs";
import { join, dirname } from "path";

const TAG = chalk.bgGreen("dev.mjs");
const require = createRequire(import.meta.url);
const pkg = require("../package.json");

/**
 * @param {{ name: string; configFile: string; writeBundle: import('rollup').OutputPlugin['writeBundle'] }} param0
 * @returns {import('rollup').RollupWatcher}
 */
function getWatcher({ name, configFile, writeBundle }) {
  return viteBuild({
    // Ensure `vite-main.config.js` and `vite-preload.config.js` correct `process.env.NODE_ENV`
    mode: process.env.NODE_ENV,
    // Options here precedence over configFile
    build: {
      watch: {},
    },
    configFile,
    plugins: [{ name, writeBundle }],
  });
}

/**
 * @returns {Promise<import('rollup').RollupWatcher>}
 */
async function watchMain() {
  /**
   * @type {import('child_process').ChildProcessWithoutNullStreams | null}
   */
  let electronProcess = null;

  /**
   * @type {import('rollup').RollupWatcher}
   */
  //let root = dirname(dirname(decodeURI(new URL(import.meta.url).pathname)));
  //const os = platform();
  //if (os == "win32") root = root.slice(1);
  //const copySrc = join(root, "os", `${os}`);
  const watcher = await getWatcher({
    name: "electron-main-watcher",
    configFile: "config/vite-main.config.js",
    writeBundle() {
      /*
      if (existsSync(copySrc)) {
        cpSync(copySrc, join(root, "dist/m"), {
          recursive: true,
        });
      }
      */
      electronProcess && electronProcess.kill();
      electronProcess = spawn(electron, ["."], {
        stdio: "inherit",
        env: Object.assign(process.env, pkg.env),
      });
    },
  });

  return watcher;
}

/**
 * @param {import('vite').ViteDevServer} viteDevServer
 * @returns {Promise<import('rollup').RollupWatcher>}
 */
async function watchPreload(viteDevServer) {
  return getWatcher({
    name: "electron-preload-watcher",
    configFile: "config/vite-preload.config.js",
    writeBundle() {
      viteDevServer.ws.send({
        type: "full-reload",
      });
    },
  });
}

// bootstrap
const viteDevServer = await createServer({
  configFile: "config/vite-web.config.js",
});

await watchPreload(viteDevServer);
await watchMain();
await viteDevServer.listen();
